package com.jet.merchant.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jet.core.enums.CommonStatus;
import com.jet.core.model.vo.PageVo;
import com.jet.core.utils.IdUtil;
import com.jet.merchant.domain.dto.ResourceDto;
import com.jet.merchant.domain.entity.ClerkAccountRoleMap;
import com.jet.merchant.domain.entity.ClerkResource;
import com.jet.merchant.domain.entity.ClerkRoleResourceMap;
import com.jet.merchant.domain.query.ResourcePageQuery;
import com.jet.merchant.domain.vo.ResourceVo;
import com.jet.merchant.mapper.ClerkResourceMapper;
import com.jet.merchant.service.IClerkAccountRoleMapService;
import com.jet.merchant.service.IClerkResourceService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jet.merchant.service.IClerkRoleResourceMapService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author author
 * @since 2025-02-25
 */
@Service
public class ClerkResourceServiceImpl extends ServiceImpl<ClerkResourceMapper, ClerkResource> implements IClerkResourceService {


    private final IClerkAccountRoleMapService clerkAccountRoleMapService;
    private final IClerkRoleResourceMapService clerkRoleResourceMapService;

    public ClerkResourceServiceImpl(IClerkAccountRoleMapService clerkAccountRoleMapService, IClerkRoleResourceMapService clerkRoleResourceMapService) {
        this.clerkAccountRoleMapService = clerkAccountRoleMapService;
        this.clerkRoleResourceMapService = clerkRoleResourceMapService;
    }

    @Override
    public void save(ResourceDto dto) {
        ClerkResource entity = new ClerkResource();
        BeanUtils.copyProperties(dto, entity);
        entity.setId(IdUtil.generateLower());
        super.save(entity);
    }

    @Override
    public void edit(String id, ResourceDto dto) {
        ClerkResource entity = new ClerkResource();
        BeanUtils.copyProperties(dto, entity);
        entity.setId(id);
        super.updateById(entity);
    }

    @Override
    public List<ResourceVo> findAllByIds(List<String> ids) {
        if (CollUtil.isEmpty(ids)) {
            return Collections.emptyList();
        }
        List<ClerkResource> resources = super.listByIds(ids);
        return resources.stream().map(x -> {
            Wrapper<ClerkResource> wrapper = new LambdaQueryWrapper<ClerkResource>()
                    .eq(ClerkResource::getPid, x.getId());

            ResourceVo vo = new ResourceVo();
            BeanUtils.copyProperties(x, vo);
            long subCount = super.count(wrapper);
            vo.setHasChildren(subCount > 0);
            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    public List<ResourceVo> findAllByRoleId(String roleId) {
        List<ClerkRoleResourceMap> roleResourceMaps = clerkRoleResourceMapService.findAllByRoleId(roleId);
        if (CollectionUtils.isEmpty(roleResourceMaps)) {
            return Collections.emptyList();
        }
        List<String> resourceIds = roleResourceMaps.stream()
                .map(ClerkRoleResourceMap::getResourceId)
                .distinct().collect(Collectors.toList());
        return findAllByIds(resourceIds);
    }

    @Override
    public List<ResourceVo> findAll() {
        List<ClerkResource> list = super.list();
        return list.stream().map(x -> {
            Wrapper<ClerkResource> wrapper = new LambdaQueryWrapper<ClerkResource>()
                    .eq(ClerkResource::getPid, x.getId());

            ResourceVo vo = new ResourceVo();
            BeanUtils.copyProperties(x, vo);
            long subCount = super.count(wrapper);
            vo.setHasChildren(subCount > 0);
            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    public List<ResourceVo> findAllByAccountId(String accountId) {
        List<String> resourceIds = findAllResourceIdByAccountId(accountId);
        if (resourceIds.isEmpty()) {
            return Collections.emptyList();
        }
        return findAllByIds(resourceIds);
    }

    private List<String> findAllResourceIdByAccountId(String accountId) {
        ClerkAccountRoleMap userRole = clerkAccountRoleMapService.findByAccountId(accountId);
        if (userRole == null) {
            return Collections.emptyList();
        }
        List<ClerkRoleResourceMap> roleResourceList = clerkRoleResourceMapService.findAllByRoleId(userRole.getRoleId());
        if (roleResourceList.isEmpty()) {
            return Collections.emptyList();
        }
        return roleResourceList.stream()
                .map(ClerkRoleResourceMap::getResourceId)
                .collect(Collectors.toList());
    }

    @Override
    public ResourceVo info(String id) {
        //返回目录和对应操作信息
        ResourceVo vo = new ResourceVo();
        ClerkResource entity = super.getById(id);
        BeanUtils.copyProperties(entity, vo);
        return vo;
    }

    @Override
    public PageVo<ResourceVo> page(ResourcePageQuery query) {
        Page<ClerkResource> tempQuery = new Page<>(query.getPageIndex(), query.getPageSize());
        Wrapper<ClerkResource> wrapper = new LambdaQueryWrapper<ClerkResource>()
                .isNull(ClerkResource::getPid);
        IPage<ClerkResource> page = super.page(tempQuery, wrapper);
        if (CollUtil.isEmpty(page.getRecords())) {
            return PageVo.result();
        }
        List<ClerkResource> resourcesParent = page.getRecords();
        List<ResourceVo> vos = resourcesParent.stream().map(x -> {
            Wrapper<ClerkResource> childWrapper = new LambdaQueryWrapper<ClerkResource>()
                    .eq(ClerkResource::getStatus, CommonStatus.ENABLED.getCode())
                    .eq(ClerkResource::getPid, x.getId());
            long subCount = super.count(childWrapper);

            ResourceVo vo = new ResourceVo();
            BeanUtils.copyProperties(x, vo);
            vo.setHasChildren(subCount > 0);
            return vo;
        }).collect(Collectors.toList());
        return PageVo.result(page, vos);
    }

    @Override
    public List<ResourceVo> findAllByPid(String pid) {
        List<ClerkResource> resources = getListByPid(pid);
        if (resources.isEmpty()) {
            return Collections.emptyList();
        }
        return resources.stream().map(x -> {
            Wrapper<ClerkResource> childWrapper = new LambdaQueryWrapper<ClerkResource>()
                    .eq(ClerkResource::getStatus, CommonStatus.ENABLED.getCode())
                    .eq(ClerkResource::getPid, x.getId());
            long subCount = super.count(childWrapper);
            ResourceVo vo = new ResourceVo();
            BeanUtils.copyProperties(x, vo);
            vo.setHasChildren(subCount > 0);
            return vo;
        }).collect(Collectors.toList());
    }

    private List<ClerkResource> getListByPid(String pid) {
        if (StrUtil.isBlank(pid)) {
            Wrapper<ClerkResource> wrapper = new LambdaQueryWrapper<ClerkResource>()
                    .eq(ClerkResource::getStatus, CommonStatus.ENABLED.getCode())
                    .isNull(ClerkResource::getPid);
            return super.list(wrapper);
        }
        Wrapper<ClerkResource> wrapper = new LambdaQueryWrapper<ClerkResource>()
                .eq(ClerkResource::getStatus, CommonStatus.ENABLED.getCode())
                .eq(ClerkResource::getPid, pid);
        return super.list(wrapper);
    }

    @Override
    public int pathValidate(long merchantNo, String accountId, String apiPath) {
//        List<ClerkResource> resources = findAll();
//        ClerkResource resource = resources.stream()
//                .filter(x -> StrUtil.isNotBlank(x.getApiPath()) &&
//                        Arrays.stream(x.getApiPath().split(",")).anyMatch(y -> y.startsWith(apiPath)))
//                .findFirst().orElse(null);
//        if (resource == null) {
//            // 接口没有在数据库配置，说明可以直接访问
//            return 1;
//        }
        List<ResourceVo> accountResources = findAllByAccountId(accountId);
//        if (accountResources.stream().noneMatch(x -> x.getId().equals(resource.getId()))) {
//            // 接口有在数据库配置，但是当前用户没权限访问
//            throw new CustomException(ResultCode.NOT_ROLE, "没有权限访问此操作");
//        }
        // 获取到功能ability,判断这个功能是否是付费功能
        // 如果是付费功能 判断当前对应的商户是否购买版本
        // 如果没有版本，拒绝访问
        // 如果购买版本，查看版本里边是否包含此功能 做通过或拒绝处理

//        ResourceVo tempResource = resources.stream()
//                .filter(x -> StrUtil.isNotBlank(x.getApiPath()) &&
//                        Arrays.stream(x.getApiPath().split(",")).anyMatch(y -> y.startsWith(apiPath)))
//                .findFirst().orElse(null);

        //result 1:免费，2:付费可以使用，-1:没有开通版本，-2:版本已过期, -3:当前版本没有此功能
//        int result = industryMerchantService.industryValid(merchantNo, resource.getPermissions());
//        switch (result) {
//            case -1:
//                throw new CustomException(ResultCode.INDUSTRY_NOT);
//            case -2:
//                throw new CustomException(ResultCode.INDUSTRY_ED);
//            case -3:
//                throw new CustomException(ResultCode.INDUSTRY_PERMISSION);
//            case 1:
//            case 2:
//            default:
//                return 1;
//        }
        return 1;
    }
}
